home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
176-200
/
disk_195
/
microemacs
/
src.zoo
/
amigados.c
next >
Wrap
C/C++ Source or Header
|
1989-03-23
|
20KB
|
861 lines
/* AMIGADOS.C: Operating specific I/O and Spawning functions
for MicroEMACS 3.10
(C)opyright 1988 by Daniel M. Lawrence
*/
#include <stdio.h>
#include "estruct.h"
#if AMIGA
#include <exec/types.h>
#include <exec/io.h>
#include <intuition/intuition.h>
#include <devices/console.h>
#include "etype.h"
#include "edef.h"
#include "elang.h"
#define INTUITION_REV 0L
#define NEW 1006L
#define CRWIDTH 8
#define CRHEIGHT 8
struct IntuitionBase *IntuitionBase;
struct Window *win;
struct IOStdReq con; /* ptr to console device driver handle */
/* Intuition Function type declarations */
struct IntuitionBase *OpenLibrary();
struct Window *OpenWindow();
struct IntuiMessage *GetMsg();
typedef struct {
short rw_code; /* normal keycode to generate */
short rw_scode; /* shifted " */
short rw_ccode; /* control " */
} RKEY;
/* raw keycode scan code to emacs keycode translation table */
RKEY keytrans[0x60] = {
/* CODE NORM SHIFT CTRL */
/* 0x00,*/ '`', '~', 0,
/* 0x01,*/ '1', '!', 0,
/* 0x02,*/ '2', '@', 0,
/* 0x03,*/ '3', '#', 0,
/* 0x04,*/ '4', '$', 0,
/* 0x05,*/ '5', '%', 0,
/* 0x06,*/ '6', '^', 0,
/* 0x07,*/ '7', '&', 0,
/* 0x08,*/ '8', '*', 0,
/* 0x09,*/ '9', '(', 0,
/* 0x0a,*/ '0', ')', 0,
/* 0x0b,*/ '-', '_', 0,
/* 0x0c,*/ '=', '+', 0,
/* 0x0d,*/ '\\', '|', 0,
/* 0x0e,*/ 0, 0, 0,
/* 0x0f,*/ 0, 0, 0,
/* 0x10,*/ 'q', 'Q', CTRL|'Q',
/* 0x11,*/ 'w', 'W', CTRL|'W',
/* 0x12,*/ 'e', 'E', CTRL|'E',
/* 0x13,*/ 'r', 'R', CTRL|'R',
/* 0x14,*/ 't', 'T', CTRL|'T',
/* 0x15,*/ 'y', 'Y', CTRL|'Y',
/* 0x16,*/ 'u', 'U', CTRL|'U',
/* 0x17,*/ 'i', 'I', CTRL|'I',
/* 0x18,*/ 'o', 'O', CTRL|'O',
/* 0x19,*/ 'p', 'P', CTRL|'P',
/* 0x1a,*/ '[', '{', 0,
/* 0x1b,*/ ']', '}', 0,
/* 0x1c,*/ 0, 0, 0,
/* 0x1d,*/ '1', SPEC|'>', 0,
/* 0x1e,*/ '2', SPEC|'N', 0,
/* 0x1f,*/ '3', SPEC|'V', 0,
/* 0x20,*/ 'a', 'A', CTRL|'A',
/* 0x21,*/ 's', 'S', CTRL|'S',
/* 0x22,*/ 'd', 'D', CTRL|'D',
/* 0x23,*/ 'f', 'F', CTRL|'F',
/* 0x24,*/ 'g', 'G', CTRL|'G',
/* 0x25,*/ 'h', 'H', CTRL|'H',
/* 0x26,*/ 'j', 'J', CTRL|'J',
/* 0x27,*/ 'k', 'K', CTRL|'K',
/* 0x28,*/ 'l', 'L', CTRL|'L',
/* 0x29,*/ ';', ':', 0,
/* 0x2a,*/ 39, 34, 0,
/* 0x2b,*/ 0, 0, 0,
/* 0x2c,*/ 0, 0, 0,
/* 0x2d,*/ '4', SPEC|'B', 0,
/* 0x2e,*/ '5', 0, 0,
/* 0x2f,*/ '6', SPEC|'F', 0,
/* this key is probably mapped on forign AIMIGA keyboards */
/* 0x30,*/ 0, 0, 0,
/* 0x31,*/ 'z', 'Z', CTRL|'Z',
/* 0x32,*/ 'x', 'X', CTRL|'X',
/* 0x33,*/ 'c', 'C', CTRL|'C',
/* 0x34,*/ 'v', 'V', CTRL|'V',
/* 0x35,*/ 'b', 'B', CTRL|'B',
/* 0x36,*/ 'n', 'N', CTRL|'N',
/* 0x37,*/ 'm', 'M', CTRL|'M',
/* 0x38,*/ ',', '<', 0,
/* 0x39,*/ '.', '>', 0,
/* 0x3a,*/ '/', '?', 0,
/* 0x3b,*/ 0, 0, 0,
/* 0x3c,*/ '.', SPEC|'D', 0,
/* 0x3d,*/ '7', SPEC|'<', 0,
/* 0x3e,*/ '8', SPEC|'P', 0,
/* 0x3f,*/ '9', SPEC|'Z', 0,
/* 0x40,*/ ' ', SHFT|' ', 0,
/* 0x41,*/ CTRL|'H', SHFT|'D', 0,
/* 0x42,*/ CTRL|'I', SHFT|'I', 0,
/* 0x43,*/ CTRL|'M', CTRL|'M', CTRL|'M',
/* 0x44,*/ CTRL|'M', CTRL|'M', CTRL|'M',
/* 0x45,*/ CTRL|'[', 0, 0,
/* 0x46,*/ SPEC|'D', 0, 0,
/* 0x47,*/ 0, 0, 0,
/* 0x48,*/ 0, 0, 0,
/* 0x49,*/ 0, 0, 0,
/* 0x4a,*/ '-', 0, 0,
/* 0x4b,*/ 0, 0, 0,
/* 0x4c,*/ SPEC|'P', SHFT|SPEC|'P', CTRL|SPEC|'P',
/* 0x4d,*/ SPEC|'N', SHFT|SPEC|'N', CTRL|SPEC|'N',
/* 0x4e,*/ SPEC|'F', SHFT|SPEC|'F', CTRL|SPEC|'F',
/* 0x4f,*/ SPEC|'B', SHFT|SPEC|'B', CTRL|SPEC|'B',
/* 0x50,*/ SPEC|'1', SHFT|SPEC|'1', CTRL|SPEC|'1',
/* 0x51,*/ SPEC|'2', SHFT|SPEC|'2', CTRL|SPEC|'2',
/* 0x52,*/ SPEC|'3', SHFT|SPEC|'3', CTRL|SPEC|'3',
/* 0x53,*/ SPEC|'4', SHFT|SPEC|'4', CTRL|SPEC|'4',
/* 0x54,*/ SPEC|'5', SHFT|SPEC|'5', CTRL|SPEC|'5',
/* 0x55,*/ SPEC|'6', SHFT|SPEC|'6', CTRL|SPEC|'6',
/* 0x56,*/ SPEC|'7', SHFT|SPEC|'7', CTRL|SPEC|'7',
/* 0x57,*/ SPEC|'8', SHFT|SPEC|'8', CTRL|SPEC|'8',
/* 0x58,*/ SPEC|'9', SHFT|SPEC|'9', CTRL|SPEC|'9',
/* 0x59,*/ SPEC|'0', SHFT|SPEC|'0', CTRL|SPEC|'0',
/* 0x5a,*/ '(', 0, 0,
/* 0x5b,*/ ')', 0, 0,
/* 0x5c,*/ '/', 0, 0,
/* 0x5d,*/ '*', 0, 0,
/* 0x5e,*/ 0, 0, 0,
/* 0x5f,*/ SPEC|'?', 0, 0,
};
/* some keyboard keys current states */
int r_shiftflag; /* right shift key */
int l_shiftflag; /* left shift key */
int r_altflag; /* right alt key */
int l_altflag; /* left alt key */
int r_amiflag; /* right amiga key */
int l_amiflag; /* left amiga key */
int ctrlflag; /* control key */
int lockflag; /* shift lock key */
/* output buffers and pointers */
#define OBUFSIZE 1024L
#define IBUFSIZE 64 /* this must be a power of 2 */
char out_buf[OBUFSIZE+1]; /* output character buffer */
int out_ptr = 0; /* index to next char to put in buffer */
/* input buffers and pointers */
#define IBUFSIZE 64 /* this must be a power of 2 */
unsigned char in_buf[IBUFSIZE]; /* input character buffer */
int in_next = 0; /* pos to retrieve next input character */
int in_last = 0; /* pos to place most recent input character */
in_init() /* initialize the input buffer */
{
in_next = in_last = 0;
}
in_check() /* is the input buffer non-empty? */
{
if (in_next == in_last)
return(FALSE);
else
return(TRUE);
}
in_put(event)
int event; /* event to enter into the input buffer */
{
in_buf[in_last++] = event;
in_last &= (IBUFSIZE - 1);
}
int in_get() /* get an event from the input buffer */
{
register int event; /* event to return */
event = in_buf[in_next++];
in_next &= (IBUFSIZE - 1);
return(event);
}
/*
* This function is called once to set up the terminal device streams.
* On VMS, it translates TT until it finds the terminal, then assigns
* a channel to it and sets it raw. On CPM it is a no-op.
*/
ttopen()
{
struct NewWindow new_win;
int i;
#if AZTEC
extern Enable_Abort; /* Turn off ctrl-C interrupt */
Enable_Abort = 0; /* for the Manx compiler */
#endif
/* open the intuition library */
IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", INTUITION_REV);
if (IntuitionBase == NULL) {
printf("%%Can not open Intuition\n");
exit(-1);
}
/* initialize the new windows attributes */
new_win.LeftEdge = 0;
new_win.TopEdge = 0;
new_win.Width = 640;
new_win.Height = 200;
new_win.DetailPen = 0;
new_win.BlockPen = 1;
new_win.Title = (unsigned char *)"MicroEMACS 3.10/Amiga";
new_win.Flags = WINDOWCLOSE | SMART_REFRESH | ACTIVATE |
WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING | SIZEBRIGHT |
RMBTRAP | NOCAREREFRESH;
new_win.IDCMPFlags = CLOSEWINDOW | NEWSIZE | MOUSEBUTTONS |
RAWKEY;
new_win.Type = WBENCHSCREEN;
new_win.FirstGadget = NULL;
new_win.CheckMark = NULL;
new_win.Screen = NULL;
new_win.BitMap = NULL;
new_win.MinWidth = 100;
new_win.MinHeight = 25;
new_win.MaxWidth = 640;
new_win.MaxHeight = 200;
/* open the window! */
win = (struct Window *)OpenWindow(&new_win);
if (win == NULL) {
printf("%%Can not open a window\n");
exit(-2);
}
/* and open up the console for output */
con.io_Data = (APTR)win;
OpenDevice("console.device", 0, &con, 0);
/* and init all the keyboard flags */
r_shiftflag = FALSE;
l_shiftflag = FALSE;
r_altflag = FALSE;
l_altflag = FALSE;
r_amiflag = FALSE;
l_amiflag = FALSE;
ctrlflag = FALSE;
lockflag = FALSE;
/* initialize our private event queue */
in_init();
/* set the current sizes */
newwidth(TRUE, 77);
newsize(TRUE, 23);
/* on all screens we are not sure of the initial position
of the cursor */
ttrow = 999;
ttcol = 999;
}
/*
* This function gets called just before we go back home to the command
* interpreter. On VMS it puts the terminal back in a reasonable state.
* Another no-operation on CPM.
*/
ttclose()
{
/* make sure there is no pending output */
ttflush();
/* and now close up shop */
CloseDevice(&con);
CloseWindow(win);
OpenWorkBench();
}
/*
* Write a character to the display. On VMS, terminal output is buffered, and
* we just put the characters in the big array, after checking for overflow.
* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
* MS-DOS (use the very very raw console output routine).
*/
ttputc(c)
char c;
{
/* add the character to the output buffer */
out_buf[out_ptr++] = c;
/* send the buffer out if we are at the limit */
if (out_ptr >= OBUFSIZE)
ttflush();
}
/*
* Flush terminal buffer. Does real work where the terminal output is buffered
* up. A no-operation on systems where byte at a time terminal I/O is done.
*/
ttflush()
{
/* if there are any characters waiting to display... */
if (out_ptr) {
out_buf[out_ptr] = 0; /* terminate the buffer string */
sendcon(out_buf); /* send them out */
out_ptr = 0; /* and reset the buffer */
}
}
/*
* Read a character from the terminal.
*/
ttgetc()
{
/* make sure there is no pending output */
nxtchr: ttflush();
/* if it is already buffered up, get it */
if (in_check())
return(in_get());
/* process an INTUITION event (possibly loading the input buffer) */
doevent();
goto nxtchr;
}
#if TYPEAH
/* typahead: Check to see if any characters are already in the
keyboard buffer
*/
typahead()
{
tcheck: /* if type ahead is already pending... */
if (in_check())
return(TRUE);
/* check the signal for IDCMP events pending */
if ((1 << win->UserPort->mp_SigBit) != 0)
return(TRUE);
/* no event in queue... no typeahead ready */
return(FALSE);
}
#endif
doevent()
{
register int eventX, eventY; /* local copies of the event info */
struct IntuiMessage *event; /* current event to repond to */
ULONG class; /* class of event */
USHORT code; /* data code */
SHORT x,y; /* mouse x/y position at time of event */
char buf[128]; /*temp buff*/
/* wait for an event to occur */
Wait(1 << win->UserPort->mp_SigBit);
/* get the event and parse it up */
while (event = GetMsg(win->UserPort)) {
class = event->Class;
code = event->Code;
eventX = event->MouseX;
eventY = event->MouseY;
ReplyMsg(event);
/* a normal keystroke? */
if (class == RAWKEY) {
dokey(code);
continue;
}
/* User clicked on the close gadget! */
if (class == CLOSEWINDOW) {
quit(FALSE, 0);
stuffibuf(255, 0, 0); /* fake a char to force quit to work */
}
/* resolve the mouse address (border adjusted) */
if (class == NEWSIZE) {
x = (win->Width - 5) / CRWIDTH;
y = (win->Height - 10) / CRHEIGHT;
} else {
x = (eventX - 5) / CRWIDTH;
y = (eventY - 10) / CRHEIGHT;
}
if (x > 77)
x = 77;
if (y > 23)
y = 23;
/* are we resizing the window? */
if (class == NEWSIZE) {
stuffibuf(MOUS | '1', x, y);
continue;
}
/* and lastly, a mouse button press */
switch (code) {
case 104: stuffibuf(MOUS | mod('a'), x, y);
break;
case 232: stuffibuf(MOUS | mod('b'), x, y);
break;
case 105: stuffibuf(MOUS | mod('e'), x, y);
break;
case 233: stuffibuf(MOUS | mod('f'), x, y);
break;
}
}
return;
}
int mod(c) /* modify a character by the current shift and control flags */
int c; /* original character */
{
/* first apply the shift and control modifiers */
if (l_shiftflag || r_shiftflag || lockflag)
c -= 32;
if (ctrlflag)
c |= CTRL;
return(c);
}
sendcon(buf) /* send a string to the console */
char *buf; /* buffer to write out */
{
/* initialize the IO request */
con.io_Data = (APTR)buf;
con.io_Length = strlen(buf);
con.io_Command = CMD_WRITE;
/* and perform the I/O */
SendIO(&con);
}
/* process an incomming keyboard code */
dokey(code)
int code; /* raw keycode to convert */
{
register int ekey; /* translate emacs key */
register int dir; /* key direction (up/down) */
char buf[NSTRING];
/* decode the direction of the key */
dir = TRUE;
if (code > 127) {
code = code & 127;
dir = FALSE;
}
/* process various shift keys */
if (code >= 0x60) {
switch (code) {
case 0x60: l_shiftflag = dir; break;
case 0x61: r_shiftflag = dir; break;
case 0x62: lockflag = dir; break;
case 0x63: ctrlflag = dir; break;
case 0x64: l_altflag = dir; break;
case 0x65: r_altflag = dir; break;
case 0x66: l_amiflag = dir; break;
case 0x67: r_amiflag = dir; break;
}
return;
}
/* up keystrokes are ignored for the rest of these */
if (dir == FALSE)
return;
/* first apply the shift and control modifiers */
if (ctrlflag)
ekey = keytrans[code].rw_ccode;
else if (l_shiftflag || r_shiftflag || lockflag)
ekey = keytrans[code].rw_scode;
else
ekey = keytrans[code].rw_code;
/* now apply the ALTD modifier */
if (r_altflag || l_altflag)
ekey |= ALTD;
/* apply the META prefix */
if (r_amiflag || l_amiflag) {
if ('a' <= ekey && ekey <= 'z')
ekey -= 32;
ekey |= META;
}
/* and place it in the input buffer */
stuffibuf(ekey, 0, 0);
}
stuffibuf(key, x, y) /* stuff a key in the input buffer */
int key; /* extended keystroke to remember */
int x, y; /* mouse position to record */
{
register int upper; /* upper extended bits of key */
/* split the extended keystroke */
upper = key >> 8;
key = key & 255;
/* if it is JUST control... encode it in! */
if (upper == (CTRL >> 8)) {
in_put(key - 64);
return;
}
/* if it is normal, just place it inqueue */
if (upper == 0) {
in_put(key);
return;
}
/* queue up an extended escape sequence */
in_put(0); /* escape indicator */
in_put(upper); /* event type */
if (upper & (MOUS >> 8)) {
in_put(x); /* x position */
in_put(y); /* y position */
}
in_put(key); /* event code */
return;
}
/*
* Create a subjob with a copy of the command intrepreter in it. When the
* command interpreter exits, mark the screen as garbage so that you do a full
* repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
* Under some (unknown) condition, you don't get one free when DCL starts up.
*/
spawncli(f, n)
{
long newcli;
/* don't allow this command if restricted */
if (restflag)
return(resterr());
mlwrite(TEXT1);
/* "[Starting new CLI]" */
sgarbf = TRUE;
Execute("NEWCLI \"CON:0/0/640/200/MicroEMACS Subprocess\"", 0L, 0L);
return(TRUE);
}
/*
* Run a one-liner in a subjob. When the command returns, wait for a single
* character to be typed, then mark the screen as garbage so a full repaint is
* done. Bound to "C-X !".
*/
spawn(f, n)
{
register int s;
char line[NLINE];
long newcli;
/* don't allow this command if restricted */
if (restflag)
return(resterr());
if ((s=mlreply("!", line, NLINE)) != TRUE)
return (s);
newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
Execute(line, 0L, newcli);
Close(newcli);
tgetc(); /* Pause. */
sgarbf = TRUE;
return(TRUE);
}
/*
* Run an external program with arguments. When it returns, wait for a single
* character to be typed, then mark the screen as garbage so a full repaint is
* done. Bound to "C-X $".
*/
execprg(f, n)
{
register int s;
char line[NLINE];
long newcli;
/* don't allow this command if restricted */
if (restflag)
return(resterr());
if ((s=mlreply("!", line, NLINE)) != TRUE)
return (s);
newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
Execute(line, 0L, newcli);
Close(newcli);
tgetc(); /* Pause. */
sgarbf = TRUE;
return(TRUE);
}
/*
* Pipe a one line command into a window
* Bound to ^X @
*/
pipecmd(f, n)
{
register int s; /* return status from CLI */
register WINDOW *wp; /* pointer to new window */
register BUFFER *bp; /* pointer to buffer to zot */
char line[NLINE]; /* command line send to shell */
static char bname[] = "command";
static char filnam[] = "ram:command";
long newcli;
/* don't allow this command if restricted */
if (restflag)
return(resterr());
/* get the command to pipe in */
if ((s=mlreply("@", line, NLINE)) != TRUE)
return(s);
/* get rid of the command output buffer if it exists */
if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
/* try to make sure we are off screen */
wp = wheadp;
while (wp != NULL) {
if (wp->w_bufp == bp) {
onlywind(FALSE, 1);
break;
}
wp = wp->w_wndp;
}
if (zotbuf(bp) != TRUE)
return(FALSE);
}
newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
strcat(line, " >");
strcat(line, filnam);
Execute(line, 0L, newcli);
s = TRUE;
Close(newcli);
sgarbf = TRUE;
if (s != TRUE)
return(s);
/* split the current window to make room for the command output */
if (splitwind(FALSE, 1) == FALSE)
return(FALSE);
/* and read the stuff in */
if (getfile(filnam, FALSE) == FALSE)
return(FALSE);
/* make this window in VIEW mode, update all mode lines */
curwp->w_bufp->b_mode |= MDVIEW;
wp = wheadp;
while (wp != NULL) {
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
/* and get rid of the temporary file */
unlink(filnam);
return(TRUE);
}
/*
* filter a buffer through an external DOS program
* Bound to ^X #
*/
filter(f, n)
{
register int s; /* return status from CLI */
register BUFFER *bp; /* pointer to buffer to zot */
char line[NLINE]; /* command line send to shell */
char tmpnam[NFILEN]; /* place to store real file name */
static char bname1[] = "fltinp";
static char filnam1[] = "ram:fltinp";
static char filnam2[] = "ram:fltout";
long newcli;
/* don't allow this command if restricted */
if (restflag)
return(resterr());
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
return(rdonly()); /* we are in read only mode */
/* get the filter name and its args */
if ((s=mlreply("#", line, NLINE)) != TRUE)
return(s);
/* setup the proper file names */
bp = curbp;
strcpy(tmpnam, bp->b_fname); /* save the original name */
strcpy(bp->b_fname, bname1); /* set it to our new one */
/* write it out, checking for errors */
if (writeout(filnam1) != TRUE) {
mlwrite(TEXT2);
/* "[Cannot write filter file]" */
strcpy(bp->b_fname, tmpnam);
return(FALSE);
}
newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
strcat(line, " <ram:fltinp >ram:fltout");
Execute(line,0L,newcli);
s = TRUE;
Close(newcli);
sgarbf = TRUE;
/* on failure, escape gracefully */
if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
mlwrite(TEXT3);
/* "[Execution failed]" */
strcpy(bp->b_fname, tmpnam);
unlink(filnam1);
unlink(filnam2);
return(s);
}
/* reset file name */
strcpy(bp->b_fname, tmpnam); /* restore name */
bp->b_flag |= BFCHG; /* flag it as changed */
/* and get rid of the temporary file */
unlink(filnam1);
unlink(filnam2);
return(TRUE);
}
/* return a system dependant string with the current time */
char *PASCAL NEAR timeset()
{
return(errorm);
}
#if COMPLET && AZTEC
/* FILE Directory routines */
char path[NFILEN]; /* path of file to find */
char rbuf[NFILEN]; /* return file buffer */
extern char *scdir();
/* do a wild card directory search (for file name completion) */
char *PASCAL NEAR getffile(fspec)
char *fspec; /* pattern to match */
{
register int index; /* index into various strings */
char fname[NFILEN]; /* file/path for DOS call */
/* first parse the file path off the file spec */
strcpy(path, fspec);
index = strlen(path) - 1;
while (index >= 0 && (path[index] != '/' &&
path[index] != '\\' && path[index] != ':'))
--index;
path[index+1] = 0;
/* construct the composite wild card spec */
strcpy(fname, path);
strcat(fname, &fspec[index+1]);
strcat(fname, "*.*");
/* save the path/wildcard off */
strcpy(path, fname);
/* and call for the first file */
return(getnfile());
}
char *PASCAL NEAR getnfile()
{
register char *sp; /* return from scdir */
/* and call for the next file */
sp = scdir(path);
if (sp == NULL)
return(NULL);
/* return the next file name! */
strcpy(rbuf, sp);
return(rbuf);
}
#else
char *PASCAL NEAR getffile(fspec)
char *fspec; /* file to match */
{
return(NULL);
}
char *PASCAL NEAR getnfile()
{
return(NULL);
}
#endif
#else
adoshello()
{
}
#endif